﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "GbmpModel.h"
#include "IExternalObject.h"
#include "NdbDataSchema.h"
#include "ElementCreationOptions.h"
#include "StringUtil.h"

namespace gcmp 
{
    class ILevelType;
    class ILevelHeaderBehavior;
    class IPlane;

    /// \brief 标高名称，由前缀、编号、后缀组成
    class LevelName
    {
    public:
        LevelName() {}
        LevelName(const std::wstring &prefix, int number, const std::wstring &suffix) :Prefix(prefix), Number(number), Suffix(suffix) {}
        std::wstring ToString() const
        {
            return Prefix + StringUtil::ToWString(Number) + Suffix;
        }
    public:
        std::wstring Prefix;
        int Number;
        std::wstring Suffix;
    };

    class GBMP_MODEL_EXPORT ILevel : public IExternalObject
    {
        DECLARE_CLASS_WITHOUT_DATA_MEMBERS(gcmp, ILevel, gcmp::IExternalObject, 2169FCAD-E07C-406F-920E-1ABDF4EA3BD3, gbmpmodel)
    public:
        virtual ~ILevel() {}

    public:
        /// \brief 创建标高
        ///
        /// \param pDoc 文档指针
        /// \param typeId 标高类型的Id
        /// \param name 标高的名称
        /// \param startPt 标高的起点
        /// \param endPt 标高的终点
        /// \param viewDir 视图的方向
        /// \param eco 元素创建选项
        /// \return 如果成功， 则返回ILevel的指针， 如果失败， 则为nullptr
        static ILevel* Create(IDocument* pDoc, ElementId typeId, const std::wstring& name, const Vector3d& startPt, const Vector3d& endPt, const Vector3d& viewDir, const ElementId &buildingId, ElementCreationOptions eco = ElementCreationOptions::Normal);
        /// \brief 创建标高
        ///
        /// \param pDoc 文档指针
        /// \param typeId 标高类型的Id
        /// \param name 标高的名称
        /// \param startPt 标高的起点
        /// \param endPt 标高的终点
        /// \param viewDir 视图的方向
        /// \param buildingId 单体的Id
        /// \param eco 元素创建选项
        /// \return 如果成功， 则返回ILevel的指针， 如果失败， 则为nullptr
        static ILevel* Create(IDocument* pDoc, ElementId typeId, const LevelName& name, const Vector3d& startPt, const Vector3d& endPt, const Vector3d& viewDir, const ElementId &buildingId, ElementCreationOptions eco = ElementCreationOptions::Normal);

    public:
        /// \brief 得到标高关联的标高类型
        /// \return 如果成功， 则返回ILevelType的指针， 如果失败， 则为nullptr
        virtual const ILevelType* GetLevelType() const = 0;

        /// \brief 得到标高的范围框
        /// \return 标高的范围框
        virtual Box3d GetBox() const = 0;

        /// \brief 得到标高值
        /// \return 标高值
        virtual double GetElevation() const = 0;

        /// \brief 设置标高值
        /// \param elevation 标高值
        /// \return 成功返回true， 失败返回false
        virtual bool SetElevation(double elevation) = 0;

        /// \brief 获得LevelHeaderBehavior的const版本
        virtual const ILevelHeaderBehavior* GetLevelHeaderBehavior() const = 0;

        /// \brief 获得LevelHeaderBehavior
        virtual ILevelHeaderBehavior* GetLevelHeaderBehavior() = 0;

        /// \brief 设置标头行为
        /// \param opBehavior 标高行为对象
        /// \return 设置成功返回true， 失败返回false
        virtual bool SetLevelHeaderBehavior(OwnerPtr<ILevelHeaderBehavior> opBehavior) = 0;

        /// \brief 添加关联的平面视图
        /// \param viewId 平面视图的id
        /// \return 成功返回true， 失败返回false
        virtual bool AddAssociatedPlanViewId(ElementId viewId) = 0;

        /// \brief 添加关联的天花板视图
        /// \param viewId 天花板视图的id
        /// \return 成功返回true， 失败返回false
        virtual bool AddAssociatedCeilingViewId(ElementId viewId) = 0;

        /// \brief 获取关联的平面视图的id
        /// \return 关联的平面视图的id
        virtual std::vector<ElementId> GetAssociatedPlanViewIds() const = 0;

        /// \brief 获取关联的天花板视图的id
        /// \return 关联的天花板视图的id
        virtual std::vector<ElementId> GetAssociatedCeilingViewIds() const = 0;

        /// \brief 获取标高的名称
        /// \return 标高的名称
        virtual std::wstring GetName() const = 0;

        /// \brief 获取标高的所在的单体的Id
        /// \return 单体的Id
        virtual ElementId GetBuildingId() const = 0;

        /// \brief 设置标高的所在的单体的Id
        /// \param buildingId 单体的Id
        /// \return 设置成功返回true， 失败返回false
        virtual bool SetBuildingId(ElementId buildingId) = 0;

        /// \brief 获取标高所在的参考平面
        /// \return 标高的参考平面
        virtual const IPlane* GetReferencePlane() const = 0;

        /// \brief 获取标高所在参考平面的RdId
        /// \return 标高参考平面的RdId
        virtual RegenDataId GetReferencePlaneRdId() const = 0;

        /// \brief mark 标高所在参考平面的RdId
        /// 临时方法
        virtual void MarkReferencePlaneRdId() = 0;

        /// \brief 移动夹点
        /// \return 成功返回true， 失败返回false
        virtual bool MoveAuxiliaryPoint(const IModelView* pModelView, const Vector3d newPoint, ElementId shapeHandleId) = 0;
    };

}// namespace gcmp
